package net.xdclass.sqlsessionfactory;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Objects;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Classname ConnectionPool
 * @Description TODO
 * @Date 2022/11/25 21:40
 * @Created by sunhao
 */
public class ConnectionPool implements IConnectionPool {

  /**
   * 空闲线程集合
   */
  private List<Connection> freeConnection = new Vector<Connection>();

  /**
   * 活动线程集合
   */
  private List<Connection> activeConnection = new Vector<Connection>();

  /**
   * 配置文件
   */
  private DbBean dbBean;

  /**
   * 记录线程总数
   */
  private AtomicInteger connCount;


  public ConnectionPool(DbBean dbBean) {
    this.dbBean = Objects.requireNonNull(dbBean);
    this.connCount = new AtomicInteger(0);
    init();
  }

  private void init() {
    //初始化链接
    try {
      for (int i = 0; i < dbBean.getInitConnections(); i++) {
        Connection newConnection = newConnection();
        if (newConnection == null) {
          return;
        }
        freeConnection.add(newConnection);
      }
    } catch (Exception e) {
      System.out.println("初始化链接失败!" + e.getMessage());
    }
  }

  /**
   * 创建连接
   */
  private Connection newConnection() {
    try {
      Class.forName(dbBean.getDriverName());
      Connection connection = DriverManager.getConnection(dbBean.getUrl(), dbBean.getUserName(),
          dbBean.getPassword());
      connCount.incrementAndGet();
      return connection;
    } catch (Exception e) {
      System.out.println(e.getMessage());
      throw new RuntimeException("创建连接失败"+e.getMessage());
    }
  }

  /**
   * 获取一个连接
   */
  @Override
  public synchronized Connection getConnection() {
    Connection connection = null;
    try {
      if (connCount.get() < dbBean.getMaxActiveConnections()) {
        if (freeConnection.size() > 0) {
          connection = freeConnection.remove(0);
        } else {
          connection = newConnection();
        }
        //校验连接是否可用
        if (isAvailable(connection)) {
          activeConnection.add(connection);
        } else {
          connCount.decrementAndGet();
          connection = getConnection();
        }
      } else {
        //没有可用的连接 等待
        wait(dbBean.getConnTimeOut());
        //重试
        connection = getConnection();
      }
    } catch (Exception ignored) {
    }
    return connection;
  }

  /**
   * 连接是否可用
   */
  private boolean isAvailable(Connection connection) {
    try {
      if (connection == null || connection.isClosed()) {
        return false;
      }
    } catch (SQLException ignored) {
    }
    return true;
  }


  /**
   * 释放连接
   */
  @Override
  public void releaseConnection(Connection connection) {
    if(connection == null){
      return;
    }
    try {
      if(isAvailable(connection)){
        if(freeConnection.size() < dbBean.getMaxConnections()){
          freeConnection.add(connection);
        }else{
          connection.close();
        }
        activeConnection.remove(connection);
        connCount.decrementAndGet();
        notifyAll();
      }
    } catch (SQLException ignored) {
    }
  }
}
